package AVL平衡二叉树;

public class AVLTreeDemo{
    public static void main(String[] args) {
        AVLTree avlTree = new AVLTree();
        int[] arr = {4,3,6,5,7,8};
        for (int j : arr) {
            Node node = new Node(j);
            avlTree.addNode(node);
        }
        System.out.println(avlTree.height());

    }
}

// AVL树
class AVLTree{
    Node root;

    public AVLTree(){

    }

    // 返回树的高度
    public int height(){
        if(root == null){
            return 0;
        }
        return root.height();
    }

    // 返回左子树的高度
    public int leftHeight(){
        if(root == null){
            return -1;
        }
        if(root.left == null){
            return 0;
        }
        return root.left.leftHeight();
    }

    // 返回右子树的高度
    public int rightHeight(){
        if(root == null){
            return -1;
        }
        if(root.right == null){
            return 0;
        }
        return root.right.rightHeight();
    }

    /**
     * 得到最小的节点
     * @param node 将node当做根节点
     * @return 返回以node为根节点的最小节点的值
     */
    public int getMinNode(Node node){
        if(node.left == null){
            return node.value;
        }
        return getMinNode(node.left);

    }

    // 删除节点
    public void deleteNode(int value){
        if(root == null){
            return;
        }else {
            Node search = search(value);
            if(search == null){
                return;
            }
            // 当前二叉树只有一个节点
            if(root.left == null && root.right == null){
                root = null;
                return;
            }

            Node parent = searchParent(value);
            if(search.left == null && search.right == null){// 删除叶子结点
                if(parent.left == search){
                    parent.left = null;
                }else{
                    parent.right = null;
                }
            } else if(search.left != null && search.right != null){// 删除有两颗子树的节点
                int minNode = getMinNode(search.right);
                Node node = search(minNode);
                deleteNode(minNode);
                search.value = minNode;
            }else{// 删除有一颗子树的节点
                if(parent.left == search){
                    if(search.left != null){
                        parent.left = search.left;
                    }else{
                        parent.left = search.right;
                    }
                }else{
                    if(search.left != null){
                        parent.right = search.left;
                    }else{
                        parent.right = search.right;
                    }
                }
            }
        }
    }

    // 查找当前节点
    public Node search(int value){
        if(root == null){
            return null;
        }else{
            return root.search(value);
        }
    }

    // 查找父节点
    public Node searchParent(int value){
        if(root == null){
            return null;
        }else{
            return root.searchParent(value);
        }
    }

    // 添加节点
    public void addNode(Node node){
        // 空树
        if(root == null){
            root = node;
        }else {
            root.addNode(node);
        }
    }

    // 中序遍历
    public void infixOrder(){
        if(root == null){
            System.out.println("二叉排序树为空树,无法遍历");
            return;
        }else{
            root.infixSort();
        }
    }
}


// 创建node节点
class Node{
    int value;
    Node left;
    Node right;

    // 左旋转方法
    private void leftRotate(){
        // 创建一个新的节点
        Node newNode = new Node(value);

        // 把当前节点的左子树赋值给新节点
        newNode.left = this.left;

        // 把当前节点右子树的左子树赋值给新节点的右节点
        if (this.right != null) {
            newNode.right = this.right.left;
        }else{
            newNode.right = null;
        }

        // 把当前节点的值替换成右子节点的值
        assert right != null;
        value = right.value;

        // 当前节点的右子树设置为右子树的右子树
        right = right.right;

        // 当前节点的左子树设置为新的节点
        left = newNode;
    }

    // 右旋转方法
    private void rightRotate(){
        // 以当前节点的值,创建新的节点
        Node newNode = new Node(value);

        // 当前节点的右子树设置为新节点的右子树
        newNode.right = right;

        // 当前节点左子树的右子树设置为新节点的左子树
        newNode.left = left.right;

        // 当前节点的值替换为左子节点的值
        value = left.value;

        // 当前节点的左子节点替换为左子节点的左子节点
        left = left.left;

        // 当前节点的右子节点替换为新节点
        right = newNode;
    }

    // 返回左子树的高度
    public int leftHeight(){
        if(left == null){
            return 0;
        }
        return left.height();
    }

    // 返回右子树的高度
    public int rightHeight(){
        if(right == null){
            return 0;
        }
        return right.height();
    }

    // 返回以当前节点为根节点的树的高度
    public int height(){
        return Math.max(left == null?0:left.height(),right == null? 0:right.height())+1;
    }

    /**
     * 查找节点
     * @param value 要查找节点的值
     * @return 找到了返回该节点,找不到返回空
     */
    public Node search(int value){
        if(value == this.value){
            return this;
        }else if(value < this.value){
            // 如果左子节点为空,直接返回空
            if(this.left == null){
                return null;
            }
            return this.left.search(value);
        }else{
            // 如果右子节点为空,直接返回空
            if(this.right == null){
                return null;
            }
            return this.right.search(value);
        }
    }

    /**
     * 查找要删除节点的父节点
     * @param value 要查找节点的值
     * @return 找到了返回this,找不到返回空
     */
    public Node searchParent(int value){
        if ((this.left != null && this.left.value == value)
                || (this.right != null && this.right.value == value)) {
            return this;
        }else{
            if(this.left != null && value < this.value){
                return this.left.searchParent(value);// 左子树递归
            }else if(this.right != null && value>= this.value){
                return this.right.searchParent(value);// 右子树递归
            }else{
                return null;// 没有找到父节点
            }
        }
    }

    // 添加节点的方法
    // 递归的形式添加节点,需要满足二叉排序树的要求
    public void addNode(Node node){
        if(node == null){
            return;
        }

        // 判断当前节点的值和传入节点的值的大小关系
        if(node.value > this.value){
            if(this.right != null) {
                // 向右递归添加
                this.right.addNode(node);
            }else{
                this.right = node;
            }
        }


        if(node.value < this.value){
            if(this.left != null) {
                // 向左递归添加
                this.left.addNode(node);
            }else{
                this.left = node;
            }
        }
        if((rightHeight() - leftHeight()) > 1){
            leftRotate();
        }

    }

    // 中序遍历
    public void infixSort(){
        if(this.left != null){
            this.left.infixSort();
        }
        System.out.println(this.value);

        if(this.right != null){
            this.right.infixSort();
        }
    }

    public Node(int value){
        this.value = value;
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                '}';
    }
}